﻿namespace MicroCloud.Message.Hangfire
{
    /// <summary>
    /// 消息Hangfire作业运行器
    /// </summary>
    [Dependency(ServiceLifetime.Singleton)]
    public class HangfireMessageJobRunner : IHangfireJobRunner
    {
        /// <summary>
        /// 初始化一个消息Hangfire作业运行器 <see cref="HangfireMessageJobRunner"/> 的新实例
        /// </summary>
        /// <param name="provider">服务提供者</param>
        public HangfireMessageJobRunner(IServiceProvider provider)
        {
            ServiceProvider = provider;
        }

        #region 属性
        /// <summary>
        /// 获取 服务提供者
        /// </summary>
        protected IServiceProvider ServiceProvider { get; }
        
        /// <summary>
        /// 获取 日志记录器
        /// </summary>
        protected ILogger Logger => ServiceProvider.GetLogger<HangfireMessageJobRunner>();

        #endregion

        #region 方法
        /// <summary>
        /// 启动作业运行器
        /// </summary>
        public void Start()
        {
            ////队列任务
            //BackgroundJob.Enqueue(() => Console.WriteLine($@"队列任务"));
            ////延时任务
            //var jobId = BackgroundJob.Schedule(() => Console.WriteLine($@"延时任务"), TimeSpan.FromMinutes(1));
            ////延续性任务执行
            //BackgroundJob.ContinueJobWith(jobId, () => Console.WriteLine($@"延续性任务执行"));
            ////定时任务
            //RecurringJob.AddOrUpdate("1", () => Console.WriteLine($@"定时任务：每年的4月12号15点52分任意秒执行 没加时区 小时+8"), "* 52 15 12 4 *");   //每年的4月12号15点52分任意秒执行 没加时区 小时+8
            //RecurringJob.AddOrUpdate("2", () => Console.WriteLine($@"定时任务：每分钟执行一次"), Cron.Minutely);      //每分钟执行一次。
            //RecurringJob.AddOrUpdate("3", () => Console.WriteLine($@"定时任务：每天18点36分 当前时区"), Cron.Daily(18, 36), new RecurringJobOptions { TimeZone = TimeZoneInfo.Local });  //每天18点36分 当前时区

            //延时任务
            //var jobId = BackgroundJob.Schedule(() => ExecuteMessageJob(), TimeSpan.FromSeconds(60));

            //定时任务
            var recurringJobId = "EaCloud_MessageJob".ToUpper();
            RecurringJob.RemoveIfExists(recurringJobId);
            RecurringJob.AddOrUpdate(recurringJobId, () => ExecuteMessageJob(recurringJobId), Cron.Minutely);      //每分钟执行一次。
            Logger.LogDebug("消息Hangfire作业运行器：开始处理编号为 {recurringJobId} 的消息作业任务。", recurringJobId);
        }

        /// <summary>
        /// 执行消息后台任务
        /// </summary>
        /// <param name="recurringJobId">任务编号</param>
        public void ExecuteMessageJob(string recurringJobId)
        {
            try
            {
                ServiceProvider.ExecuteScopedWork(provider =>
                {
                    var messageService = provider.GetService<IMessageService>();
                    //处理延时消息
                    var timeNow = DateTime.Now;
                    var msgDtos = messageService.Messages.Where(o => !o.IsSent).ToList<MessageEntity, MessageOutputDto>();
                    if (msgDtos != null && msgDtos.Count > 0)
                    {
                        foreach (var dto in msgDtos)
                        {
                            var messageJobId = messageService.GetMessageSendJobId(dto.Id.ToString());
                            RecurringJob.RemoveIfExists(messageJobId);
                            //是否立即发送
                            TimeSpan timeSpan = new(dto.SendTime.Ticks - timeNow.Ticks);
                            if (timeSpan.TotalMinutes <= 1)
                            {
                                messageService.SendMessages(dto.Id);
                                Logger.LogDebug("消息Hangfire作业运行器：发送编号为 {id} 的消息任务。", dto.Id);
                            }
                            else
                            {
                                var sendTime = dto.SendTime;
                                var cronString = CronHelper.GetCronString(sendTime, false);
                                RecurringJob.AddOrUpdate(messageJobId, () => messageService.SendMessages(dto.Id), cronString, new RecurringJobOptions { TimeZone = TimeZoneInfo.Local });
                                Logger.LogDebug("消息Hangfire作业运行器：创建编号为 {messageJobId} 的延时消息任务。", messageJobId);
                            }
                        }
                    }
                    //处理自动删除已发送消息
                    var msgEntities = messageService.Messages.Where(o => o.IsSent && o.StorageDays > 0).ToList();
                    if (msgEntities != null && msgEntities.Count > 0)
                    {
                        foreach (var entity in msgEntities)
                        {
                            var messageJobId = messageService.GetMessageDeleteJobId(entity.Id.ToString());
                            RecurringJob.RemoveIfExists(messageJobId);
                            //是否立即删除
                            TimeSpan timeSpan = new(entity.SendTime.AddDays(entity.StorageDays).Ticks - timeNow.Ticks);
                            if (timeSpan.TotalMinutes <= 1)
                            {
                                messageService.DeleteMessages(entity.Id);
                                Logger.LogDebug("消息Hangfire作业运行器：删除编号为 {id} 的消息记录。", entity.Id);
                            }
                            else
                            {
                                var deleteTime = entity.SendTime.AddDays(entity.StorageDays);
                                var cronString = CronHelper.GetCronString(deleteTime, false);
                                RecurringJob.AddOrUpdate(messageJobId, () => messageService.DeleteMessages(entity.Id), cronString, new RecurringJobOptions { TimeZone = TimeZoneInfo.Local });
                                Logger.LogDebug("消息Hangfire作业运行器：创建编号为 {messageJobId} 的消息记录删除任务。", messageJobId);
                            }
                        }
                    }

                    //处理模板消息
                    var tempDtos = messageService.TemplateMessages.ToList<TemplateMessage, TemplateMessageOutputDto>();
                    if (tempDtos != null && tempDtos.Count > 0)
                    {
                        foreach (var dto in tempDtos)
                        {
                            var messageJobId = messageService.GetMessageTemplateJobId(dto.Id.ToString());
                            RecurringJob.RemoveIfExists(messageJobId);
                            if (!dto.CronExpression.IsMissing() && dto.Enabled)
                            {
                                RecurringJob.AddOrUpdate(messageJobId, () => messageService.SendTemplateMessages(dto.Id), dto.CronExpression, new RecurringJobOptions { TimeZone = TimeZoneInfo.Local });
                                Logger.LogDebug("消息Hangfire作业运行器：创建编号为 {messageJobId} 的模板消息任务。", messageJobId);
                            }
                        }
                    }

                });

                RecurringJob.RemoveIfExists(recurringJobId);
                Logger.LogDebug("消息Hangfire作业运行器：完成处理编号为 {recurringJobId} 的消息作业任务。", recurringJobId);
            }
            catch (System.Exception ex)
            {
                Logger.LogError(ex, "消息Hangfire作业运行器：处理错误，{recurringJobId} - {message}", recurringJobId, ex.Message);
            }
        }

        #endregion

    }
}
